/**
 * @file base.h
 * @note examples:
 * @note     int a1=10, b1 = 11;
 * @note     Swap(a1, b1);
 * @note     int* a2 = &a1, *b2 = &b1;
 * @note     Swap(a2, b2);
 * @note     vector<int> a, b;
 * @note     Swap(a, b);
 * @author babear.wangz
 * @date 2011-02-17, Lantern Festival
 */

#ifndef VBASE_BASE_H
#define VBASE_BASE_H

#include <stdio.h>

template <typename type, size_t size> struct StandardTypeSwap;
#define OPT_STAN_TYPE_SWAP(V)        \
    V(1, uint8_t)                    \
    V(2, uint16_t)                   \
    V(4, uint32_t)                   \
    V(8, uint64_t)

#define MakeStandardTypeSwap(N, NType)                            \
template <typename type> struct StandardTypeSwap<type, N>         \
{                                                                 \
    static void swap(type& a, type& b)                            \
    {                                                             \
        NType& x = reinterpret_cast<NType&>(                      \
                *reinterpret_cast<NType*>(&a));                   \
        NType& y = reinterpret_cast<NType&>(                      \
                *reinterpret_cast<NType*>(&b));                   \
        x = x^y;                                                  \
        y = x^y;                                                  \
        x = x^y;                                                  \
    }                                                             \
};
OPT_STAN_TYPE_SWAP(MakeStandardTypeSwap)
#undef MakeStandardTypeSwap

template <typename type>
class TypeAttr {
public:
    static const bool COMMONTYPE = false;
    static void swap(type& a, type& b)
    {
        a.swap(b);
    }
};

#define OPT_BASE_COMMON_TYPE(V)     \
    V(char)                         \
    V(unsigned char)                \
    V(int)                          \
    V(unsigned int)                 \
    V(long)                         \
    V(unsigned long)                \
    V(short)                        \
    V(unsigned short)               \
    V(long long)                    \
    V(unsigned long long)           \
    V(float)                        \
    V(double)

#define MakeBaseTypeAttr(type)                           \
template<> class TypeAttr<type> {                        \
public:                                                  \
    static const bool COMMONTYPE = true;                 \
    static void swap(type& a, type& b)                   \
    {                                                    \
        StandardTypeSwap<type, sizeof(type)>::swap(a, b);\
    }                                                    \
};

OPT_BASE_COMMON_TYPE(MakeBaseTypeAttr)
#undef MakeBaseTypeAttr 

template<typename type> class TypeAttr<type*>
{
public:
    static const bool COMMONTYPE = true;
    static void swap(type*& a, type*& b)
    {
        StandardTypeSwap<type*, sizeof(type*)>::swap(a, b);
    }
};

template <typename type>
void Swap(type& a, type& b)
{
    if (&a == &b) return;
    TypeAttr<type>::swap(a, b);
}

#endif

